package com.ruoyi.common.domin;


import org.apache.commons.lang3.ArrayUtils;

import java.util.Arrays;

/**
 * @ClassName TypeConvertUtils
 * @Description 类型转换工具类
 * @Author 张永永
 * @Date 2020-11-12 16:32
 * @Version 1.0.0.0
 **/
public class TypeConvertUtils {

    /**
     * 获取字节类型高四位
     * @param data
     * @return
     */
    public static int getHeightFour(byte data){
        int heightFour = ((data & 0xf0) >> 4);
        return heightFour;
    }

    /**
     * 获取字节类型低四位
     * @param data
     * @return
     */
    public static int getLowFour(byte data){
        int lowFour = (data & 0x0f);
        return lowFour;
    }

    /**
     * 数组反序
     * @param arr
     * @return
     */
    public final static String[] reverseStringArray(String[] arr){
        for (int i = 0; i < arr.length/2; i++) {
            //交换元素
            String temp = arr[arr.length -i -1];
            arr[arr.length -i -1] = arr[i];
            arr[i] = temp;
        }
        return arr;
    }

    /**
     * 小端传输字节数组转换为字符串（反转字节）
     *
     * @param byteArray
     * @return
     */
    public final static String byteArrayReverseToString(byte[] byteArray) {
        try {
            String hexString = "";
            for (int i = byteArray.length - 1; i >= 0; i--) {
                String hexTemp = Integer.toHexString(byteArray[i] & 0xFF);
                if (hexTemp.length() == 1) {
                    hexTemp = '0' + hexTemp;
                }
                hexString = hexString + hexTemp;
            }
            return hexString.toUpperCase();
        } catch (Exception ex) {
            throw ex;
        }
    }

    /**
     * todo 电源版本转换
     * @param byteArray
     * @return
     */
    public final static String bateArrayReverseToHexVersion(byte[] byteArray){
        String hexString = "";
        for (int i = byteArray.length - 1; i >= 0; i--) {
            String hexTemp = Integer.toHexString(byteArray[i] & 0xFF);
            if (hexTemp.length()<2){
                hexTemp="0"+hexTemp;
            }
            hexTemp = hexTemp.substring(0,1)+"."+hexTemp.substring(1,2);
            if(i !=0 ){
                hexString = hexString + hexTemp+".";
            }else{
                hexString = hexString + hexTemp;
            }
        }
        return "V "+ hexString.toUpperCase();
    }

    /**
     * 小端传输字节数组转换为字符串（反转字节）并且转换为版本号
     *
     * @param byteArray
     * @return
     */
    public final static String byteArrayReverseToVersionString(byte[] byteArray) {
        try {
            int num = 0;
            for (int i = 0; i < byteArray.length; i++) {
                num += (byteArray[i] & 0xFF) << (8 * i);
            }
            return "V "+(num/100)+"."+(num%100);

//            String hexString = "";
//            for (int i = byteArray.length - 1; i >= 0; i--) {
//                String hexTemp = Integer.toHexString(byteArray[i] & 0xFF);
//                if(i !=0 ){
//                    hexString = hexString + hexTemp+".";
//                }else{
//                    hexString = hexString + hexTemp;
//                }
//            }
//            return "V "+ hexString.toUpperCase();
        } catch (Exception ex) {
            throw ex;
        }
    }

    /**
     * 字节数组转换为字符串
     *
     * @param byteArray
     * @return
     */
    public final static String byteArrayToString(byte[] byteArray) {
        try {
            String hexString = "";
            for (int i = 0; i < byteArray.length; i++) {
                String hexTemp = Integer.toHexString(byteArray[i] & 0xFF);
                if (hexTemp.length() == 1) {
                    hexTemp = '0' + hexTemp;
                }
                hexString = hexString + hexTemp;
            }
            return hexString.toLowerCase();
        } catch (Exception ex) {
            throw ex;
        }
    }

    public final static String byteArrayToHexString(byte[] bytes) {
        if (null == bytes) {
            return null;
        }

        StringBuilder sb = new StringBuilder(bytes.length << 1);

        for(int i = 0; i < bytes.length; ++i) {
            char[] hex = "0123456789abcdef".toCharArray();
            sb.append(hex[(bytes[i] & 0xf0) >> 4])
                    .append(hex[(bytes[i] & 0x0f)])
            ;
        }
        for (int i = 2; i < sb.length(); i+=3) {

            sb.insert(i,"-");
        }

        return sb.toString();
    }


    /**
     * 将byte数组转换为整数（小端传输方式）
     *
     * @param byteArray
     * @return
     */
    public static int bytesToReverseInt(byte[] byteArray) {
        int num = 0;
        for (int i = 0; i < byteArray.length; i++) {
            num += (byteArray[i] & 0xFF) << (8 * i);
        }
        return num;
    }

    /**
     * 将byte数组转换为整数（大端传输方式）
     *
     * @param byteArray
     * @return
     */
    public static int bytesToInt(byte[] byteArray) {
        int num = 0;
        for (int i = 0; i < byteArray.length; i++) {
            num += (byteArray[i] & 0xFF) << (8 * (byteArray.length-i-1));
        }
        return num;
    }

    /**
     * 获取字节在内存中某一位的值,采用字符取值方式
     */
    public static Integer getBitByByte(byte b, int index) {
        if (index >= 8) {
            return null;
        }
        Integer val = null;
        String binStr = byteToBin(b);
        val = Integer.parseInt(String.valueOf(binStr.charAt(index)));
        return val;
    }

    /**
     * 把单个字节转换成二进制字符串
     */
    public static String byteToBin(byte b) {
        String zero = "00000000";
        String binStr = Integer.toBinaryString(b & 0xFF);
        if (binStr.length() < 8) {
            binStr = zero.substring(0, 8 - binStr.length()) + binStr;
        }
        return binStr;
    }

    /**
     * 反转字节数组（按照每4字节反转）
     *
     * @param inputArray 需要反转的字节数组
     * @return 反转后的字节数组
     */
    public static byte[] reverseArray(byte[] inputArray) {
        //TODO 如果字节长度不等于4，则返回null
        if (inputArray.length % 4 != 0) {
            return null;
        }
        //计算CRC输入字节数组
        byte[] outputArray = inputArray;
        //按照每4字节反转字节序列
        for (int i = 0; i <= outputArray.length - 4; i = i + 4) {
            byte[] byteArray = {outputArray[i], outputArray[i + 1], outputArray[i + 2], outputArray[i + 3]};
            ArrayUtils.reverse(byteArray);
            outputArray[i] = byteArray[0];
            outputArray[i + 1] = byteArray[1];
            outputArray[i + 2] = byteArray[2];
            outputArray[i + 3] = byteArray[3];
        }
        return outputArray;
    }

    /**
     * 从当前数组中截取子数组
     *
     * @param inputArray 原始数组
     * @param from       数组起始索引
     * @param length     截取长度
     * @return 返回截取后数组
     */
    public static byte[] getSubArray(byte[] inputArray, int from, int length) {
        return Arrays.copyOfRange(inputArray, from, from + length);
    }

    /**
     * byte数据 转为16进制String
     *
     * @param byteInput 字节数据输入
     * @return 16进制形式的字符串
     */
    public static String byteToHexString(byte byteInput) {
        String hex = Integer.toHexString(byteInput & 0xFF);
        if (hex.length() == 1) {
            hex = '0' + hex;
        }
        String ret = hex.toUpperCase();
        return ret;
    }

    /**
     * 根据字符串填充字节数组
     *
     * @param subStr 输入的字符串
     * @return 字节数组
     */
    public static byte[] stringToBytesTemp(String subStr) {
        try {
            byte[] returnData = new byte[subStr.length() / 2];
            for (int i = 0; i < subStr.length() / 2; i++) {
                //填充字节数组
                returnData[i] = Integer.valueOf(subStr.substring(i * 2, i * 2 + 2)).byteValue();
            }
            return returnData;
        } catch (Exception ex) {
            return null;
        }
    }


    /**
     * 根据字符串填充字节数组
     *
     * @param subStr 输入的字符串
     * @return 字节数组
     */
    public static byte[] stringToBytes(String subStr) {
        try {
            byte[] returnData = new byte[subStr.length() / 2];
            for (int i = 0; i < subStr.length() / 2; i++) {
                //填充字节数组
                returnData[i] = Integer.valueOf(subStr.substring(i * 2, i * 2 + 2), 16).byteValue();
            }
            return returnData;
        } catch (Exception ex) {
            return null;
        }
    }

    /**
     * 将int型数据转换为byte数组,返回的结果为字节数组反转
     *
     * @param value 输出参数
     * @param len   byte数组长度
     * @return
     */
    public static byte[] intToConverseBytes(int value, int len) {
        byte[] b = new byte[len];
//        for (int i = 0; i < len; i++) {
//            b[len - i - 1] = (byte)((value >> 8 * i) & 0xff);
//        }
        for (int i = 0; i < len; i++) {
            b[i] = (byte) ((value >> 8 * i) & 0xff);
        }
        return b;
    }

    /**
     * 将int型数据转换为byte数组
     *
     * @param value 输出参数
     * @param len   byte数组长度
     * @return
     */
    public static byte[] intToBytes(int value, int len) {
        byte[] b = new byte[len];
        for (int i = 0; i < len; i++) {
            b[i] = (byte) ((value >> 8 * i) & 0xff);
        }
        return b;
    }

    /**
     * 将int型数据转换为byte数组 小端
     *
     * @param value 输出参数
     * @param len   byte数组长度
     * @return
     */
    public static byte[] intToLittleBytes(int value, int len) {
        byte[] b = new byte[len];
        for (int i = 0; i < len ; i++) {
            b[i] = (byte) ((value >> 8 * (len-i-1)) & 0xff);
        }
        return b;
    }


    /**
     * 反转字符串并转换为字节数组
     *
     * @param inputString 原始字符串
     * @return 字节数组
     */
    public static byte[] reverseStringToBytes(String inputString) {
        try {
            byte[] returnData = new byte[inputString.length() / 2];
            int flag = returnData.length;
            for (int i = 0; i < inputString.length() / 2; i++) {
                //填充字节数组
                returnData[--flag] = Integer.valueOf(inputString.substring(i * 2, i * 2 + 2), 16).byteValue();
            }
            return returnData;
        } catch (Exception ex) {
            return null;
        }
    }


    /**
     * 补齐并反转字符串
     *
     * @param inputString 输入字符串
     * @param polishLen   补齐后长度（必须为偶数）
     * @return
     */
    public static String polishAndReverse(String inputString, int polishLen) {
        int strLen = inputString.length();
        StringBuffer sb = null;
        while (strLen < polishLen) {
            sb = new StringBuffer();
            sb.append("0").append(inputString);// 左补0
            inputString = sb.toString();
            strLen = inputString.length();
        }
        String reverseResult = "";
        //低字节在前高字节在后，所以需要反转
        for (int j = inputString.length() - 2; j >= 0; j = j - 2) {
            reverseResult = reverseResult + inputString.substring(j, j + 2);
        }
        return reverseResult;
    }


    /**
     * 合并字节数组
     *
     * @param a
     * @param b
     * @return
     */
    public static byte[] concatBytes(byte[] a, byte[] b) {
        byte[] c = new byte[a.length + b.length];
        System.arraycopy(a, 0, c, 0, a.length);
        System.arraycopy(b, 0, c, a.length, b.length);
        return c;
    }

    /**
     * 合并数组
     *
     * @param a
     * @param b
     * @param <T>
     * @return 合并后的数组
     */
    public static <T> T[] concatArray(T[] a, T[] b) {

        final int alen = a.length;

        final int blen = b.length;

        if (alen == 0) {

            return b;

        }

        if (blen == 0) {

            return a;

        }

        final T[] result = (T[]) java.lang.reflect.Array.

                newInstance(a.getClass().getComponentType(), alen + blen);

        System.arraycopy(a, 0, result, 0, alen);

        System.arraycopy(b, 0, result, alen, blen);

        return result;

    }

    /**
     * 合并多个数组
     *
     * @param rest 动态数组参数
     * @return
     */
    public static byte[] concatAll(byte[]... rest) {
        int totalLength = 0;
        for (byte[] array : rest) {
            totalLength += array.length;
        }
        byte[] result = new byte[totalLength];

        //T[] result = Arrays.copyOf(first, totalLength);
        int offset = 0;
        for (byte[] array : rest) {
            System.arraycopy(array, 0, result, offset, array.length);
            offset += array.length;
        }
        return result;
    }

    public static String  bytesToReverseIntDefaultStringValue(byte[] byteArray){
        int num = 0;
        for (int i = 0; i < byteArray.length; i++) {
            num += (byteArray[i] & 0xFF) << (8 * i);
        }
        if (num==65535){
         return "";
        }else {
            return num+"";
        }
    }

    /**
     * 计算modbus CRC16校验码
     *
     * @param bytes 字节数组
     * @return {@link String} 校验码
     * @since 1.0
     */
    public static byte[] getModbusCrc(byte[] bytes) {
        int CRC = 0x0000ffff;
        int POLYNOMIAL = 0x0000a001;
        int i, j;
        for (i = 0; i < bytes.length; i++) {
            CRC ^= ((int) bytes[i] & 0x000000ff);
            for (j = 0; j < 8; j++) {
                if ((CRC & 0x00000001) != 0) {
                    CRC >>= 1;
                    CRC ^= POLYNOMIAL;
                } else {
                    CRC >>= 1;
                }
            }
        }
        byte[] modbuscrc = new byte[2];
        for (int k = 0; k < 2; k++) {
            modbuscrc[k] = (byte) ((CRC >> 8 * k) & 0xff);
        }
        return modbuscrc;
    }
}
